<?php 

class Ladder_model extends CI_Model {
	
	private $USER_TABLE = 'users';
	private $CHALLENGE_UP_RANGE, $CHALLENGE_DOWN_RANGE;
	
	private $select_array = array(0 => 'account', 1 => 'score', 2 => 'ladder_wins', 3 => 'ladder_losses'); 
	
	private $table;
	
	function __construct(){
		parent::__construct();
		
		//Load challenge settings
		$this->config->load('challenge_settings');
		
		$this->CHALLENGE_UP_RANGE = $this->config->item('challenge_up_amount');
		$this->CHALLENGE_DOWN_RANGE = $this->config->item('challenge_down_amount');
	}
	
	function get_table() {
		return $this->table;
	}
	
	function get_rank($name){
		return $this->table[$name]['rank'];
	}
	
	//Refresh table data
	function refresh_table() {
		//Fetch columns indicated in select_array
		$this->db->select($this->select_array);
		$this->db->order_by('score', 'desc');
		
		//get results from db
		$query = $this->db->get($this->USER_TABLE);
		
		//Build multidimensional associative array
		$this->table = array(); //Initialize table as empty array
		foreach($query->result_array() as $row){
			$name = $row['account']; //This is going to be the row index	
			$this->table[$name] = array_merge(array('rank' => 1), $row); //Initialize the row with key username
			
			//Set custom columns
			$total_games = $row['ladder_wins'] + $row['ladder_losses'];
			$this->table[$name]['account'] = anchor('/profile/show/'.$name,$name);
			$this->table[$name]['ratio'] = $total_games == 0 ? '0%' : (round(100*$row['ladder_wins']/$total_games, 1)).'%';
		}
		
		$this->set_rank();
		$this->set_challenge();
	}
	
	/**
	 * Sets the rank column of the table
	 * @return unknown_type
	 */
	private function set_rank(){
		
		//Initialize rank variables
		$rank_count = 1;
		$prev_rank = 1;
		$prev_score = 99999; //No one should ever have this score
		
		//Iterate through each row and give correct rank
		foreach($this->table as $name => $row){
			
			if($row['score'] == $prev_score){
				$rank = $prev_rank;
			}
			else {
				$rank = $rank_count;
				$prev_rank = $rank;
			}
			
			$this->table[$name]['rank'] = $rank; //Set rank
			
			$prev_score = $row['score'];
			$rank_count++;
		}
	}
	
	//Sets the challenge column. Rank must be set first.
	private function set_challenge(){
		$cur_account = $this->session->userdata('account');
		if(isset($this->table[$cur_account])) $this->table[$cur_account]['challenge'] = '--';
		else {
			//This condition will occur if person viewing ladder is not logged in
			foreach($this->table as $name => $row) $this->table[$name]['challenge'] = 'NO';
			return;
		}
		
		//Set array pointer to the lowest player with the same rank as myself
		$array = $this->table;
		do{
			if($this->table[key($array)]['rank'] > $this->table[$cur_account]['rank']) break;
			next($array);
		} while(!is_null(key($array)));
		
		if(is_null(key($array))) end($array); //If loop was broken naturally, set pointer to last item
		else prev($array); //Loop was broken by break, back up one item
		
		//Create new references to array for use in iteration. These references have their own internal pointers.
		//One will be iterated through forwards and the other through backwards
		$goUp = $array; 
		$goDown = $array;
		
		//Set challenge up targets
		$final_rank = 0;
		$count = 0;
		while(!is_null(key($goUp))){
			if(key($goUp) == $cur_account); //Do nothing if this is my account
			else if($count < $this->CHALLENGE_UP_RANGE || $this->table[key($goUp)]['rank'] == $final_rank){
				$javascript = 'setChallengeTarget(\'' . key($goUp) . '\'); new Boxy(\'#hidden_form\', {modal : true});';
				$this->table[key($goUp)]['challenge'] = '<a style="cursor:pointer" onclick="'.$javascript.'">YES</a>';
				if(++$count >= $this->CHALLENGE_UP_RANGE) $final_rank = $this->table[key($goUp)]['rank'];
			}
			else $this->table[key($goUp)]['challenge'] = 'NO';
			
			prev($goUp);
		}
		
		//Set challenge down targets
		$final_rank = 0;
		$count = 0;
		next($goDown);
		while(!is_null(key($goDown))){
			if($count < $this->CHALLENGE_DOWN_RANGE || $this->table[key($goDown)]['rank'] == $final_rank){
				$javascript = 'setChallengeTarget(\'' . key($goDown) . '\'); new Boxy(\'#hidden_form\', {modal : true});';
				$this->table[key($goDown)]['challenge'] = '<a style="cursor:pointer" onclick="'.$javascript.'">YES</a>';
				if(++$count >= $this->CHALLENGE_DOWN_RANGE) $final_rank = $this->table[key($goDown)]['rank'];
			}
			else $this->table[key($goDown)]['challenge'] = 'NO';
			
			next($goDown);
		}
	}
	
	//Method used to return all the valid targets for a player
	function get_challenge_list($challenger){
		
		//Get current player's score
		$this->db->where('account', $challenger);
		$this->db->select('score');
		$res = $this->db->get($this->USER_TABLE);
		$row = $res->row_array();
		if(!empty($row)) $score = $row['score'];
		else return array();
		
		//Get lowest challengeable score
		$this->db->select('score');
		$this->db->where('score <', $score);
		$this->db->order_by('score', 'desc');
		$this->db->limit($this->CHALLENGE_DOWN_RANGE);
		$res = $this->db->get($this->USER_TABLE);
		$lower = $res->last_row('array');
		
		//Get highest challengeable score
		$this->db->select('score');
		$this->db->where('score >=', $score);
		$this->db->where('account !=', $challenger);
		$this->db->order_by('score', 'asc');
		$this->db->limit($this->CHALLENGE_UP_RANGE);
		$res = $this->db->get($this->USER_TABLE);
		$higher = $res->last_row('array');
		
		//Select anyone with scores between min & max score
		$this->db->select('account');
		$lowscore = empty($lower) ? $score : $lower['score'];
		$highscore = empty($higher) ? $score : $higher['score'];
		$this->db->where('score >=', $lowscore);
		$this->db->where('score <=', $highscore);
		$this->db->where('account !=', $challenger);
		$res = $this->db->get($this->USER_TABLE);
		$targets = $res->result_array();
	
		return $targets;
	}
	
}